#include "car_lib.h"

GLint window;
Car yo, com;
GLint camara, mode,grafo;

GLdouble ang;

Bomb* bombas[20];

// para el rastro de aceite
OilTrace yo_aceite, com_aceite;

void display(){

    glMatrixMode(GL_MODELVIEW);
    glClearColor(0.23,0.21,0.53,1.0f);
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      
    
    // CAMARAS
    // 3ra Persona
    if (camara == 1){
        glRotatef(90,0,1,0);   
        glRotatef((-1)*yo.vision,0,1,0);
        glTranslatef((-1)*(yo.x-cos((360-yo.vision)/R2G)*4),(-1)*(0.5+yo.y),
                            (-1)*(yo.z-sin((360-yo.vision)/R2G)*4));
    }
    // Arriba
    if (camara == 2){
        glRotatef(-90,0,0,1); 
        glRotatef(90,0,1,0); 
        glTranslatef(60,0,0);
        glRotatef(90,0,0,1);  
        glTranslatef((-1)*yo.x,0,(-1)*yo.z);
    }
    // Retrovisor
    if (camara == 3){
        glRotatef(-90,0,0,1); 
        glRotatef(90,0,1,0); 
        glTranslatef(700,0,0);
        glRotatef(90,0,0,1);  
        glTranslatef(0,0,0);
//        glRotatef(90,0,1,0);   
//        glTranslatef(0.0,-0.3,0.0);
    }

    GLint i, j;
    
    if(grafo){
        // grafo
        for(i=0;i<nn;i++){
            glColor3f(0.0,1.0,0.0);
            glBegin(GL_LINE_STRIP);
                glVertex3f(nodos[i].x1,0,nodos[i].z1);
                glVertex3f(nodos[i].x2,0,nodos[i].z2);
                glVertex3f(nodos[i].x3,0,nodos[i].z3);
                glVertex3f(nodos[i].x2,0,nodos[i].z2);
                glVertex3f(nodos[i].x1,0,nodos[i].z1);
                glVertex3f(nodos[i].x3,0,nodos[i].z3);
            glEnd();
            glPushMatrix();
                glTranslatef(nodos[i].x,0,nodos[i].z);
                if (nodos[i].yo_aceite && nodos[i].com_aceite) glColor3f(0.05,0.75,0.75);
                if (nodos[i].yo_aceite && !nodos[i].com_aceite) glColor3f(0.05,0.05,0.05);
                if (!nodos[i].yo_aceite && nodos[i].com_aceite) glColor3f(0.1,0.7,0.1);
                glutSolidSphere(0.5,10,10);
            glPopMatrix();
            glColor3f(1.0,1.0,1.0);
            if (nodos[i].v1 != -1){
                glBegin(GL_LINE_STRIP);
                    glVertex3f(nodos[i].x,0,nodos[i].z);
                    glVertex3f(nodos[nodos[i].v1].x,0,nodos[nodos[i].v1].z);
                glEnd();
            }
            if (nodos[i].v2 != -1){
                glBegin(GL_LINE_STRIP);
                    glVertex3f(nodos[i].x,0,nodos[i].z);
                    glVertex3f(nodos[nodos[i].v2].x,0,nodos[nodos[i].v2].z);
                glEnd();
            }
            if (nodos[i].v3 != -1){
                glBegin(GL_LINE_STRIP);
                    glVertex3f(nodos[i].x,0,nodos[i].z);
                    glVertex3f(nodos[nodos[i].v3].x,0,nodos[nodos[i].v3].z);
                glEnd();
            }
        }
    }

    // Piso!
    //glColor3f(0.5,0.1,0.01);
    glColor3f(1.0,1.0,1.0);
    glEnable(GL_TEXTURE_2D);
    glPushMatrix();
    glBindTexture(GL_TEXTURE_2D, asfalto[0]);
    for (i=-20;i<20;i++){
        for (j=-20;j<20;j++){
            glBegin(GL_QUADS);
                glTexCoord2f(1.0,1.0); glVertex3f((i+1)*25.0f, -0.38f,  (j+1)*25.0f);
                glTexCoord2f(1.0,0.0); glVertex3f((i+1)*25.0f, -0.38f,  j*25.0f);
                glTexCoord2f(0.0,0.0); glVertex3f( i*25.0f,    -0.38f,  j*25.0f);
                glTexCoord2f(0.0,1.0); glVertex3f( i*25.0f,    -0.38f,  (j+1)*25.0f);
            glEnd();
        }
    }
    glPopMatrix();
    glDisable(GL_TEXTURE_2D);
    
    // gotas de aceite
    for (i=yo_aceite.gotaP,j=0;j<200;i++,j++){
        i%=200;
        glColor3f(0.05,0.05,0.05);
        glPushMatrix();
            glTranslatef(yo_aceite.aceiteXZ[i][0],-0.38,yo_aceite.aceiteXZ[i][1]);
            glScalef(yo_aceite.aceiteXZ[i][2],1,yo_aceite.aceiteXZ[i][2]);
            glutSolidSphere(0.2,10,10);
        glPopMatrix();
    }
    for (i=com_aceite.gotaP,j=0;j<200;i++,j++){
        i%=200;
        glColor3f(0.1,0.7,0.1);
        glPushMatrix();
            glTranslatef(com_aceite.aceiteXZ[i][0],-0.38,com_aceite.aceiteXZ[i][1]);
            glScalef(com_aceite.aceiteXZ[i][2],1,com_aceite.aceiteXZ[i][2]);
            glutSolidSphere(0.2,10,10);
        glPopMatrix();
    }
    
    // *** Items *** (Cambiar los cubos por algo mas representativo!!!)
    // balas:
    glPushMatrix();
        glColor3f(0,0,0);
        glTranslatef(nodos[amno].x,1,nodos[amno].z);
        glBegin(GL_LINE_STRIP);
            glVertex3f(0,0,0);
            glVertex3f(0,100,0);
        glEnd();
        glPushMatrix();
            glScalef(5,5,5);
            glRotatef(ang,0,1,0);
            construirBomba(1.00,1.00,1.00,45);        
        glPopMatrix();
    glPopMatrix();
    // vida
    glPushMatrix();
        glColor3f(1,1,1);
        glTranslatef(nodos[vida].x,0.5,nodos[vida].z);
        glBegin(GL_LINE_STRIP);
            glVertex3f(0,0,0);
            glVertex3f(0,100,0);
        glEnd();
        glPushMatrix();
            glRotatef(ang,0,1,0);
            dibujaCruz();
        glPopMatrix();
    glPopMatrix();

    // limite de nivel;
    for (i=-200;i<=200;i+=5){
        glColor3f(1.0,1.0,1.0);
        glPushMatrix();
            glTranslatef(i,0,200);
            glutSolidSphere(0.2,10,10);
        glPopMatrix();
        glPushMatrix();
            glTranslatef(i,0,-200);
            glutSolidSphere(0.2,10,10);
        glPopMatrix();
        glPushMatrix();
            glTranslatef(200,0,i);
            glutSolidSphere(0.2,10,10);
        glPopMatrix();
        glPushMatrix();
            glTranslatef(-200,0,i);
            glutSolidSphere(0.2,10,10);
        glPopMatrix();
    }
    
    // carrito yo
    glPushMatrix();
        glColor3f(1.0,0.0,0.0);
        glTranslatef(yo.x,yo.y,yo.z);
        glRotatef(yo.vision,0.0,1.0,0.0);
        //glutWireSphere(0.45,10,10);
        construirCarro(yo.ang_canon,yo.ang_ruedas,0.00,0.00,1.00,yo.anim_canon);
    glPopMatrix();

    // carrito com
    glPushMatrix();
        glColor3f(1.0,0.0,0.0);
        glTranslatef(com.x,com.y,com.z);
        glRotatef(com.vision,0.0,1.0,0.0);
        //glutWireSphere(0.45,10,10);
        construirCarro(com.ang_canon,com.ang_ruedas,1.00,0.00,0.00,com.anim_canon);
    glPopMatrix();
    
    for(i=0; i<20; i++){
        if (bombas[i] == NULL) continue;
        else {
            glPushMatrix();            
                glTranslatef(bombas[i]->x,bombas[i]->y,bombas[i]->z);
                if (!bombas[i]->blow){
                    if (bombas[i]->side) 
                        glRotatef(bombas[i]->m_dir+180,0.0,1.0,0.0);
                    else
                        glRotatef(bombas[i]->m_dir,0.0,1.0,0.0);
                    if (bombas[i]->quien )construirBomba(0.00,0.00,1.00,bombas[i]->v_dir);
                    else construirBomba(1.00,0.00,0.00,bombas[i]->v_dir);
                }
                else {
                    dibujaExplosion(bombas[i]->blow);
                    bombas[i]->blow++;
                    if (bombas[i]->blow>50) {
                        if(bombas[i]->hit){
                            yo.hit = 0;
                            com.hit = 0;
                        }
                        bombas[i]->blow=0;
                        bombas[i]=NULL;
                    }
                }
            glPopMatrix();
            if (bombas[i] != NULL){
                glPushMatrix();
                    glColor3f(1,0,0);
                    glTranslatef(bombas[i]->tx,0,bombas[i]->tz);
                    glRotatef(90,1,0,0);
                    glutSolidTorus(0.01,1,10,10);
                glPopMatrix();
            }
        }
    }
    
    // mapa
    // edificios
    glPushMatrix();
        glTranslatef(-100,0,-100);
        glRotatef(180,0,1,0);
        construirEdificio();        
    glPopMatrix();
    glPushMatrix();
        glTranslatef(100,0,100);
        glRotatef(-90,0,1,0);
        construirEdificio();
    glPopMatrix();
    // Q1
    glPushMatrix();
        glTranslatef(-50,0,-50);
        glScalef(1,1,-1);
        glRotatef(-90,0,1,0);
        construirPared();
    glPopMatrix();
    glPushMatrix();
        glTranslatef(0,0,-150);
        glRotatef(-90,0,1,0);
        construirMurito();
    glPopMatrix();
    // Q2
    glPushMatrix();
        glTranslatef(50,0,-50);
        glScalef(1,1,-1);
        construirPared();
    glPopMatrix();
    glPushMatrix();
        glTranslatef(150,0,0);
        glRotatef(180,0,1,0);
        construirMurito();
    glPopMatrix();
    // Q3
    glPushMatrix();
        glTranslatef(50,0,50);
        glScalef(1,1,-1);
        glRotatef(90,0,1,0);
        construirPared();
    glPopMatrix();    
    glPushMatrix();
        glTranslatef(0,0,150);
        glRotatef(90,0,1,0);
        construirMurito();
    glPopMatrix();
    // Q4
    glPushMatrix();
        glTranslatef(-50,0,50);
        glScalef(1,1,-1);
        glRotatef(180,0,1,0);
        construirPared();
    glPopMatrix();
    glPushMatrix();
        glTranslatef(-150,0,0);
        construirMurito();
    glPopMatrix();    
    // rampas
    glPushMatrix();
        glTranslatef(100,0,-100);
        glRotatef(-90,0,1,0);
        construirRampa();
    glPopMatrix();
    glPushMatrix();
        glTranslatef(-100,0,100);
        glRotatef(90,0,1,0);
        construirRampa();
    glPopMatrix();
    
    // esto es para que lo siguiente se dibuje SIEMPRE sobre todo
    // i.e. el mapa no se meta dentro de un carro o el escenario
    glDisable(GL_DEPTH_TEST);    
    /// HUD!!!!
    glBegin(GL_LINES);
        glColor3f(0,1,0);
        glVertex3f(yo.x-cos((390-yo.vision)/R2G)*1.5,-0.25+yo.y,yo.z-sin((390-yo.vision)/R2G)*1.5);
        glVertex3f(yo.x-cos((390-yo.vision)/R2G)*1.5,0.1+yo.y,yo.z-sin((390-yo.vision)/R2G)*1.5);
        
        glVertex3f(yo.x-cos((400-yo.vision)/R2G)*1.695,-0.25+yo.y,yo.z-sin((400-yo.vision)/R2G)*1.695);
        glVertex3f(yo.x-cos((400-yo.vision)/R2G)*1.695,0.1+yo.y,yo.z-sin((400-yo.vision)/R2G)*1.695);
        
        glVertex3f(yo.x-cos((390-yo.vision)/R2G)*1.5,-0.25+yo.y,yo.z-sin((390-yo.vision)/R2G)*1.5);
        glVertex3f(yo.x-cos((400-yo.vision)/R2G)*1.695,-0.25+yo.y,yo.z-sin((400-yo.vision)/R2G)*1.695);
        
        glVertex3f(yo.x-cos((390-yo.vision)/R2G)*1.5,0.1+yo.y,yo.z-sin((390-yo.vision)/R2G)*1.5);
        glVertex3f(yo.x-cos((400-yo.vision)/R2G)*1.695,0.1+yo.y,yo.z-sin((400-yo.vision)/R2G)*1.695);
    glEnd();    
    glColor3f(0,0,1);
    glPushMatrix();
        glTranslatef(yo.x-cos((((-1)*0.025*yo.x+395)-yo.vision)/R2G)*((-1)*0.0004875*yo.x+1.5975),
                    (-1)*0.000875*yo.z-0.075+yo.y,
                    yo.z-sin((((-1)*0.025*yo.x+395)-yo.vision)/R2G)*((-1)*0.0004875*yo.x+1.5975));
        glutSolidSphere(0.01,5,5);
    glPopMatrix();    
    glColor3f(1,0,0);
    glPushMatrix();
        glTranslatef(yo.x-cos((((-1)*0.025*com.x+395)-yo.vision)/R2G)*((-1)*0.0004875*com.x+1.5975),
                    (-1)*0.000875*com.z-0.075+yo.y,
                    yo.z-sin((((-1)*0.025*com.x+395)-yo.vision)/R2G)*((-1)*0.0004875*com.x+1.5975));
        glutSolidSphere(0.01,5,5);
    glPopMatrix();
    glPushMatrix();
        glTranslatef(yo.x-cos((325-yo.vision)/R2G)*1.7,
                     yo.y,
                     yo.z-sin((325-yo.vision)/R2G)*1.7);
        dibujaVel(yo.v_mag,yo.time_units);
    glPopMatrix();    
    
    glEnable(GL_DEPTH_TEST);
    
    glutSwapBuffers();
}

void reshape(int w, int h){
    float aspectratio;
    if (h==0)
        h=1;
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    aspectratio = (float) w / (float) h;
    gluPerspective(35.0f, aspectratio, 1.0, 3000.0);
}

void keystroke(int key, int x, int y){
    if (key == GLUT_KEY_F1){
        camara=1;
    }
    if (key == GLUT_KEY_F2){
        camara=2;
    }
    if (key == GLUT_KEY_F3){
        camara=3;
    }
    if (key == GLUT_KEY_F4){
        if (mode) mode = 0;
        else mode = 1;
    }
    if (key == GLUT_KEY_F5){
        if (grafo) grafo = 0;
        else grafo = 1;
    }
    if (key == GLUT_KEY_UP){
        if(mode) yo.acelera=1;
    }
    if (key == GLUT_KEY_LEFT){
        if(mode){
            yo.ang_ruedas = (-1)*ANG_RUEDAS;
            yo.a_mag = 90;
        }
    }
    if (key == GLUT_KEY_RIGHT){
        if(mode){
            yo.ang_ruedas = ANG_RUEDAS;
            yo.a_mag = -90;
        }
    }
    if (key == GLUT_KEY_DOWN){
        if(mode) yo.acelera=-1;
    }    
}

void keystrokeChar(unsigned char key, int x, int y){
    if (key == 'x'){
        if(mode) yo.salta = 1;
    }
    if (key == ' '){
        if(mode){
            if(yo.balas){
                yo.balas--;
                yo.anim_canon = 1;
            }
            else printf(" Recargar!! \n");
        }
    }
    if (key == 'w'){
        if(mode) yo.ang_canon += 10;
    }
    if (key == 's'){
        if(mode) yo.ang_canon -= 10;
    }
    
    if (yo.ang_canon > 90)
        yo.ang_canon = 90;
    if (yo.ang_canon < 0)
        yo.ang_canon = 0;
}

void timer(int extra){
    ang++;
    if (mode){ // Asi puedo utilizar F4 como pausa!!!!
        //if(com.anim_canon == 1) dispara(&com,bombas,0);
        if(yo.anim_canon == 1) dispara(&yo,bombas,1);
        gameStats(&yo,&com,&mode);
        decide(&com,bombas,&yo_aceite);
        int i;
        for(i=0; i<20; i++){
            if (bombas[i] == NULL) continue;
            else{
                updateB(bombas[i]);
                explota(&com,bombas[i]);
                explota(&yo,bombas[i]);
            }
        }
        rastroAceite(&yo,&com,&yo_aceite,&com_aceite);
        update(&yo,&com);
        update(&com,&yo);
    }
    glutPostRedisplay();
    glutTimerFunc(extra,&timer,extra);
}

void soltarTecla(int key, int x, int y){
    if (key == GLUT_KEY_UP || key == GLUT_KEY_DOWN) 
        yo.acelera = 0;
    if (key == GLUT_KEY_LEFT || key == GLUT_KEY_RIGHT){
        yo.ang_ruedas = 0;
        yo.a_mag = 0;
    }
}

int main(int argc, char** args){

    srand(time(NULL));
    
    cargarMapa("./data/mapa1");
    
    pasos = 0;
    
    // inicializo el carrito yo
    setCar(&yo,-80.0,-80.0);
    //yo.vidas=1;
    // ***********************            

    // inicializo el carrito com
    setCar(&com,95.0,120.0);
    com.nodo = 38;
    com.nodosig = 38;
    com.nodot = 38;
    // ***********************            

    state.id = 1;
    state.bomb = -1;
    state.car = &yo;
    printf(" Vagar \n");

    camara = 1;
    mode = grafo = 0;
    b = t = 0;
    
    //inicializo items
    setItems();
    
	glutInit(&argc,args);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(800, 600);
	glutInitWindowPosition(220, 90);
	window = glutCreateWindow("Death Race");
	//glutFullScreen();
	
	glutIgnoreKeyRepeat(1);
	glutDisplayFunc(&display);
	glutReshapeFunc(&reshape);
	glutSpecialFunc(&keystroke);
	glutKeyboardFunc(&keystrokeChar);
	
	glutSpecialUpFunc(&soltarTecla);
	glutTimerFunc(10,&timer,25);
	
	glEnable (GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	
	cargarTextura();

	glutMainLoop();
	return 0;
}
